package mscloud.filter;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import mscloud.config.CaptchaStrategyContext;
import mscloud.config.properties.CaptchaProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;

import static com.elevenms.common.core.constant.Constants.*;

/**
 * @Datetime: 2025年07月26日16:19
 * @Author: Eleven52AC
 * @Description: 验证码过滤器工厂，对指定路径的请求进行验证码校验。
 */
@Component
public class ValidateCodeGatewayFilterFactory extends AbstractGatewayFilterFactory<Object> {

    /**
     * 需要验证码校验的路径
     */
    private final static String[] NEED_VALIDATE_CODE_URLS = {"/api/user/login", "/api/user/register"};

    @Autowired
    private CaptchaProperties captchaProperties;

    @Autowired
    private CaptchaStrategyContext captchaStrategyContext;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;


    @Override
    public GatewayFilter apply(Object config) {
        return new GatewayFilter() {
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                ServerHttpRequest request = exchange.getRequest();
                String requestPath = request.getURI().getPath();

                // 验证码功能关闭或不匹配路径则放行
                Boolean enabled = captchaProperties.getEnabled();
                String type = captchaProperties.getType();
                if (!StrUtil.equalsAnyIgnoreCase(requestPath, NEED_VALIDATE_CODE_URLS) || !enabled) {
                    return chain.filter(exchange);
                }

                // 校验验证码
                return resolveBodyFromRequest(request)
                        .flatMap(body -> {
                            JSONObject obj = JSON.parseObject(body);
                            captchaStrategyContext.getStrategy(type).checkCaptcha(obj.getString(CAPTCHA_CODE), obj.getString(CAPTCHA_UUID),stringRedisTemplate);
                            return chain.filter(exchange);
                        })
                        .onErrorResume(e -> {
                            // todo 响应待优化
                            return Mono.error(e);
                        });
            }
        };
    }




    /**
     * @Author: Eleven52AC
     * @Description: 从ServerHttpRequest中解析请求体内容，将数据缓冲区转换为UTF-8编码的字符串
     * @param request HTTP服务器请求对象，包含请求体数据
     * @return 返回包含请求体内容的Mono字符串，用于响应式编程处理
     */
    private Mono<String> resolveBodyFromRequest(ServerHttpRequest request) {
        // 将请求体中的数据缓冲区连接并转换为字符串
        return DataBufferUtils.join(request.getBody())
                .map(dataBuffer -> {
                    // 读取数据缓冲区中的字节数据
                    byte[] bytes = new byte[dataBuffer.readableByteCount()];
                    dataBuffer.read(bytes);
                    DataBufferUtils.release(dataBuffer); // 释放内存
                    // 将字节数据转换为UTF-8编码的字符串
                    return new String(bytes, StandardCharsets.UTF_8);
                });
    }



}
